#ifndef __WIZ_FILE_HPP__SHANHAOBO_19800429__
#error only be included in "WizFile.hpp"
#endif /*__WIZ_FILE_HPP__SHANHAOBO_19800429__*/

namespace Wiz
{
    namespace File
    {
        //////////////////////////////////////////////////////////////////////////

        WIZ_INLINE ::Wiz::File::Ptr Open(::Wiz::String::In InFileName, ::Wiz::UInt::In OpenOpts)
        {
            if (::Wiz::Bit::IsAnySet(OpenOpts, ::Wiz::File::OpenOptions::eOpenCreate))
            {
                if (::Wiz::File::Exist(InFileName) == ::Wiz::Bool::False)
                {
                    ::Wiz::File::CreateEmptyFile(InFileName);
                }
            }

            if (::Wiz::Bit::IsAllSet(OpenOpts, ::Wiz::File::OpenOptions::eOpenRead | ::Wiz::File::OpenOptions::eOpenWrite))
            {
                return ::fopen(InFileName.GetCStr(), "r+b");
            }

            if (::Wiz::Bit::IsSet(OpenOpts, ::Wiz::File::OpenOptions::eOpenRead))
            {
                return ::fopen(InFileName.GetCStr(), "rb");
            }

            if (::Wiz::Bit::IsSet(OpenOpts, ::Wiz::File::OpenOptions::eOpenWrite))
            {
                return ::fopen(InFileName.GetCStr(), "wb");
            }

            return WIZ_NULLPTR;
        }

        WIZ_INLINE ::Wiz::Void::Type Close(::Wiz::File::Ptr InFilePtr)
        {
            ::fclose(InFilePtr);
        }

        //////////////////////////////////////////////////////////////////////////

        WIZ_INLINE ::Wiz::Bool::Type Read(::Wiz::File::Ptr InFilePtr, ::Wiz::Byte::OutPtr OutBufferPtr, ::Wiz::Int64::In InSize)
        {
            long CurPos = ftell(InFilePtr);
            if (ReadAndAdvance(InFilePtr, OutBufferPtr, InSize))
            {
                return ::fseek(InFilePtr, CurPos, SEEK_SET) == 0;
            }

            return false;
        }

        WIZ_INLINE ::Wiz::Bool::Type Write(::Wiz::File::Ptr InFilePtr, ::Wiz::Byte::InPtr InBufferPtr, ::Wiz::Int64::In InSize)
        {
            long CurPos = ftell(InFilePtr);
            if (WriteAndAdvance(InFilePtr, InBufferPtr, InSize))
            {
                return ::fseek(InFilePtr, CurPos, SEEK_SET) == 0;
            }

            return false;
        }

        WIZ_INLINE ::Wiz::Bool::Type ReadAndAdvance(::Wiz::File::Ptr InFilePtr, ::Wiz::Byte::OutPtr OutBufferPtr, ::Wiz::Int64::In InSize)
        {
            return ::fread((::Wiz::Void::Ptr)OutBufferPtr, (size_t)InSize, sizeof(::Wiz::Byte::Type), InFilePtr) == sizeof(::Wiz::Byte::Type);
        }

        WIZ_INLINE ::Wiz::Bool::Type WriteAndAdvance(::Wiz::File::Ptr InFilePtr, ::Wiz::Byte::InPtr InBufferPtr, ::Wiz::Int64::In InSize)
        {
            return ::fwrite((::Wiz::Void::Ptr)InBufferPtr, (size_t)InSize, sizeof(::Wiz::Byte::Type), InFilePtr) == sizeof(::Wiz::Byte::Type);
        }

        //////////////////////////////////////////////////////////////////////////

        WIZ_INLINE ::Wiz::USize32::Type CurrentPosition(::Wiz::File::Ptr InFilePtr)
        {
            return ::Wiz::USize32::Type(::ftell(InFilePtr));
        }

        WIZ_INLINE ::Wiz::Void::Type  MoveTo(::Wiz::File::Ptr InFilePtr, ::Wiz::Int64::In InPos)
        {
            ::fseek(InFilePtr, long(InPos), SEEK_SET);
        }

        WIZ_INLINE ::Wiz::Void::Type  MoveToBegin(::Wiz::File::Ptr InFilePtr)
        {
            ::fseek(InFilePtr, 0, SEEK_SET);
        }

        WIZ_INLINE ::Wiz::Void::Type  MoveToEnd(::Wiz::File::Ptr InFilePtr)
        {
            ::fseek(InFilePtr, 0, SEEK_END);
        }

        WIZ_INLINE ::Wiz::Void::Type  Move(::Wiz::File::Ptr InFilePtr, ::Wiz::Int64::In InPos)
        {
            ::fseek(InFilePtr, long(InPos), SEEK_CUR);
        }

        WIZ_INLINE ::Wiz::Void::Type Expend(::Wiz::File::Ptr InFilePtr, ::Wiz::Byte::InPtr DataPtr, ::Wiz::Int64::In InPos)
        {
            long CurPos = ::ftell(InFilePtr);
            if (::fseek(InFilePtr, 0, SEEK_END) == 0)
            {
                WriteAndAdvance(InFilePtr, DataPtr, InPos);
                ::fseek(InFilePtr, CurPos, SEEK_SET);
            }
        }
        //////////////////////////////////////////////////////////////////////////
    } /// end of namespace File
} /// end of namespace Wiz
